interface IPaddingRequest {
  request: () => Promise<any>;
  resolve: (_res: any) => void;
  reject: (_err: any) => void;
}

export class RequestManager {
  maxConcurrentRequests: number;
  pendingRequests: IPaddingRequest[];
  activeRequests: number;

  constructor(maxConcurrentRequests: number) {
    this.maxConcurrentRequests = maxConcurrentRequests;
    this.pendingRequests = [];
    this.activeRequests = 0;
  }

  /** 添加请求 */
  async addRequest(request: () => Promise<any>): Promise<any> {
    return new Promise<any>((resolve, reject) => {
      this.pendingRequests.push({request, resolve, reject});
      this.processRequests();
    });
  }

  async processRequests() {
    while (this.activeRequests < this.maxConcurrentRequests && this.pendingRequests.length) {
      const request = this.pendingRequests.shift()!;
      this.sendRequest(request);
    }
  }

  /** 发送请求 */
  async sendRequest(pendingRequests: IPaddingRequest) {
    this.activeRequests++;
    const {request, resolve, reject} = pendingRequests;

    request()
      .then(resolve)
      .catch(reject)
      .finally(() => {
        this.activeRequests--;
        this.processRequests();
      });
  }
}
